﻿using Futajma.MigrationStudio.DataDefinition;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace Futajma.MigrationStudio.LiveLinkExporter
{
    class SeparateFileLoader
    {
        public event ProcessUpdate ProcessUpdate;

        const int MINDOCUMENTSPERFILE = 1000;

        Dictionary<string, List<XElement>> _allDocuments = new Dictionary<string, List<XElement>>();
        Dictionary<string, List<XElement>> _separateFileList = new Dictionary<string, List<XElement>>();

        int _separateFileCount = 0;
        string _timeStamp;

        public SeparateFileLoader(string timeStamp)
        {
            _timeStamp = timeStamp;
        }

        void InternalProcessUpdate(Update update)
        {
            if (ProcessUpdate != null)
            {
                ProcessUpdate(this, update);
            }
        }

        public void LoadFiles(string folder, string[] files)
        {
            InternalProcessUpdate(new Update() { Information = "Clean up and load item definition files", MessageType = MessageType.Info });
            _allDocuments.Clear();
            _separateFileList.Clear();
            _separateFileList.Add(CurrentFileName, new List<XElement>());

            _separateFileCount = 0;
            //var files = Directory.GetFiles(folder, "*.stdx");

            InternalProcessUpdate(new Update() { Information = string.Format("{0} files found", files.Count()), MessageType = MessageType.Info });

            foreach (var file in files)
            {
                string path = string.Format(@"{0}\{1}", folder, file);
                InternalProcessUpdate(new Update() { Information = string.Format("Processing file {0}", file), MessageType = MessageType.Info });

                XDocument separateFileDoc = null;
                XmlReaderSettings xmlReaderSettings = new XmlReaderSettings { CheckCharacters = false };
                
                using (XmlReader xmlReader = XmlReader.Create(path, xmlReaderSettings))
                {
                    xmlReader.MoveToContent();
                    separateFileDoc = XDocument.Load(xmlReader);
                }

                //XDocument separateFileDoc = XDocument.Load(path, );

                var documents = separateFileDoc.Descendants("document");

                foreach (var doc in documents)
                {
                    var id = (string)doc.Descendants("property")
                        .First(x => (string)x.Attribute("ref") == "liveLinkId");

                    if (!_allDocuments.ContainsKey(id))
                    {
                        _allDocuments.Add(id, new List<XElement>());
                    }
                    InternalProcessUpdate(new Update() { Information = string.Format("Document with id {0} added", id), MessageType = MessageType.Info });
                    _allDocuments[id].Add(doc);
                }

                var dataItems = separateFileDoc.Descendants("dataItem");

                foreach (var dataItem in dataItems)
                {
                    var id = (string)dataItem.Descendants("property")
                        .First(x => (string)x.Attribute("ref") == "liveLinkId");

                    if (!_allDocuments.ContainsKey(id))
                    {
                        _allDocuments.Add(id, new List<XElement>());
                    }
                    InternalProcessUpdate(new Update() { Information = string.Format("DataItem with id {0} added", id), MessageType = MessageType.Info });
                    _allDocuments[id].Add(dataItem);
                }
            }
        }

        public void OpenNewFolder()
        {
            if (_separateFileList[CurrentFileName].Count > MINDOCUMENTSPERFILE)
            {
                _separateFileCount++;
                _separateFileList.Add(CurrentFileName, new List<XElement>());
                InternalProcessUpdate(new Update() { Information = string.Format("New Folder opened {0}", CurrentFileName), MessageType = MessageType.Info });
            }
        }

        public void AddToFile(XElement element)
        {
            _separateFileList[CurrentFileName].Add(element);
        }

        public List<XElement> this[string key]
        {
            get
            {
                if (_allDocuments.ContainsKey(key))
                {
                    return _allDocuments[key];
                }
                else
                {
                    throw new Exception(string.Format("Export doesn't contain the requested item with id {0}. Please use the proper export.", key));
                }
            }
        }

        public string CurrentFileName
        {
            get
            {
                return _separateFileCount == 0 ? string.Format("SeparateFile_{0}.stdx", _timeStamp) : string.Format("SeparateFile {0}_{1}.stdx", _separateFileCount, _timeStamp);
            }
        }

        public void SaveFiles(string newLocation)
        {
            foreach (var key in _separateFileList.Keys)
            {
                XElement el = new XElement("exportData",
                    new XElement("ecm",
                        new XAttribute("type", "LiveLink"),
                        new XAttribute("version", "2.1 API"),
                        new XAttribute("location", "")));
                // add all documents
                var docs = new XElement("documents");
                el.Add(docs);

                var arOfDocs = _separateFileList[key].ToArray().Where(p => p.Name == "document");

                //var des = _separateFileList[key].Descendants("document");

                docs.Add(arOfDocs);

                // add all dataitems
                var dataItems = new XElement("dataItems");
                el.Add(dataItems);

                var arOfItems = _separateFileList[key].ToArray().Where(p => p.Name == "dataItem");

                //des = _separateFileList[key].Descendants("dataItem");
                dataItems.Add(arOfItems);


                var file = string.Format(@"{0}\{1}", newLocation, key);
                InternalProcessUpdate(new Update() { Information = string.Format(@"Save file {0} to {1}", key, file), MessageType = MessageType.Info });

                XmlWriterSettings settings = new XmlWriterSettings();
                //settings.Encoding = new UnicodeEncoding(false, false); // no BOM in a .NET string
                settings.OmitXmlDeclaration = true;
                settings.CheckCharacters = false;
                StringWriter sw = new StringWriter();
                //using (XmlWriter xw = XmlWriter.Create(sw, settings))
                // or to write to a file...
                using (XmlWriter xw = XmlWriter.Create(file, settings))
                {
                    el.Save(xw);
                }


            }
        }
    }
}
